<template>
	<view class="ifun-tree-picker">
		<picker mode="multiSelector" :value="selectIndex" ref="picker" :range-key="options.key" :range="viewData"
			:disabled="disabled" @columnchange="handleChange" @change="handleConfirm">
			<slot>
				<!-- <input :placeholder="placeholder" inputmode="none" :value="selectText" /> -->
				<text class="empty-select" v-if="!selectText">{{placeholder}}</text>
				<text class="select-text" v-else>{{selectText}}</text>
			</slot>

		</picker>
	</view>
</template>

<script>
	// 节点信息映射
	const DefaultOptions = {
		label: 'label',
		value: 'value',
		key: 'label',
		children: 'children'
	}
	export default {
		name: 'ifun-tree-picker',
		props: {
			disabled: Boolean,
			data: {
				type: Array,
				default: () => ([])
			},
			treeOptions: {
				type: Object,
				defautl: () => ({})
			},
			value: {
				type: [Object, Array],
				default: () => ({})
			},
			clearable: Boolean,
			checkStrictly: Boolean,
			placeholder: {
				type: String,
				default: '请选择'
			},
			valueFormat: Function,
			lazy: {
				type: Boolean,
				default: false
			},
			load: Function
		},
		data() {
			return {
				selectValue: [],
				// picker 的自身属性
				selectIndex: [],
				// 当前的节点数据
				viewData: [],

			};
		},
		watch: {
			data: {
				immediate: true,
				deep: true,
				handler(arr) {
					// 默认第一条数据
					this.viewData = [JSON.parse(JSON.stringify(arr))]
					// this.viewData = [arr];
					// 是否严格遵循父子节点不关联
					if (this.checkStrictly) {
						this.handleFormatData(this.viewData[0]);
					}
					if (this.clearable) {
						const {
							value,
							label
						} = this.options
						this.viewData[0].unshift({
							[value]: '',
							[label]: ''
						})
					}
					
					// 处理默认值
					this.handleFormatDefault(this.value);
					// 初始化后续的数据
					this.initViewData();
					
				}
			},
			value: {
				immediate: true,
				deep: true,
				handler() {
					// 处理默认值
					this.handleFormatDefault(this.value);
				}
			}
		},
		computed: {
			options() {
				return {
					...DefaultOptions,
					...this.treeOptions
				}
			},
			selectText() {

				let len = this.selectValue.length
				if (len < 1) {
					return ''
				}
				if (this.valueFormat && typeof this.valueFormat == 'function') {
					return this.valueFormat(this.selectValue)
				}
				return this.selectValue[len - 1][this.options.label]
			},
		},
		methods: {
			/**
			 * 
			 */
			handleFormatData(data) {

				let len = data.length;
				const {
					children,
					value,
					label
				} = this.options
				for (let i = 0; i < len; i++) {
					let item = data[i]
					if (item[children] && item[children].length > 0) {
						this.handleFormatData(item[children])
						item[children].unshift({
							[value]: '',
							[label]: ''
						});
					}
				}
			},
			/**
			 * 处理默认值是数组时的情况
			 * 解决不同父级，相同子级的数据展示问题
			 * @param {Array} arr
			 */
			handleFormatDefaultOfArray(arr) {
				let len = arr.length;
				if(len<1){
					return
				}
				const {
					value,
					children
				} = this.options
				// 
				let selectData = this.data;
				let selectIndexs = [];
				let selectValues = [];
				for (let i = 0; i < len; i++) {
					let info = arr[i];
					let index = selectData.findIndex(item => item[value] == info[value])

					if (index > -1) {
						selectIndexs.push(index);
						selectValues.push(selectData[index]);
						selectData = selectData[index][children] || [];
					}
				}
				if (selectIndexs.length<1) {
					// 没有找到对应的数据，直接显示给定值
					this.selectValue = arr;
					return
				} 
				this.selectIndex = [...selectIndexs];
				this.selectValue = [...selectValues];
			},
			/**
			 * 
			 * @param {Object} info
			 */
			handleFormatDefault(info) {
				let $this = this;
				
				// 接受默认值参数为数组，填充默认值
				if (Array.isArray(info)) {
					this.handleFormatDefaultOfArray(info)
					return
				}
				let value = info[this.options.value]
				if (!value) {
					return;
				}


				function deepFind(obj, arr, key, indexArr, index) {

					const {
						value,
						children
					} = $this.options

					if (obj[value] == key) {
						arr.push(obj);
						indexArr.push(index);
						return true;
					}
					if (obj[children] && obj[children].length > 0) {
						arr.push(obj);
						indexArr.push(index);
						return obj[children].some((item, sindex) => deepFind(item, arr, key, indexArr, sindex))
					}
					return false;
				}

				for (let i = 0, len = this.data.length; i < len; i++) {
					let item = this.data[i]
					// 选择的数据对象
					let arr = [];
					// 选择的数据下表
					let indexArr = [];
					let bool = deepFind(item, arr, value, indexArr, i);
					if (bool) {
						// arr.push(info);
						this.selectValue = [...arr]
						this.selectIndex = [...indexArr]
						return
					}
				}
				// 没有找到对应的数据，直接显示给定值
				this.selectValue = [info]

			},
			initViewData() {

				const {
					children
				} = this.options
				let info = this.data[0]
				// 默认值选中
				let index = 0;
				if (this.selectIndex[index] != undefined) {
					info = this.data[this.selectIndex[index]]
				}
				while (info && info[children] && info[children].length > 0) {

					// 默认第一条数据
					this.viewData.push(info[children])
					// 处理默认值
					index++;
					if (this.selectIndex[index] != undefined) {
						// 继续处理下一层级的选择数据
						info = info[children][this.selectIndex[index]]
					} else {
						info = info[children][0];
						this.selectIndex.push(0);
					}
				}
				
				// 数据初始化后，调用一次懒加载
				
				if(this.lazy){
					let columnIndex = 0;
					if(this.selectIndex.length>0){
						columnIndex = this.selectIndex.length-1;
					}
					this.handleLazyLoad({column:columnIndex,value:0})
				}
			},
			/**
			 * 异步加载时，逻辑处理，数据由内部直接处理
			 * 
			 */
			handleLazyLoad({
				column
			}) {
				
				let $this = this;
				const {
					value,
					label
				} = this.options
				
				// 解决 不同父级、同一子级的问题，懒加载后默认选中该子级
				// this.selectIndex.length = column + 1;
				this.viewData.length = column + 1;

				// let selectValues = this.selectIndex.map((val, index) => this.viewData[index][val]);
				let selectValues = this.viewData.map((items,index)=>items[this.selectIndex[index]]);
				
				if(!selectValues[column]){
					return
				}
				this.load(selectValues[column], selectValues, (data) => {
					
					// 回调、处理异步加载数据
					if (Array.isArray(data) && data.length > 0) {
						
						// 是否严格遵循父子节点不关联
						if ($this.checkStrictly) {
							data.unshift({
								[value]: '',
								[label]: ''
							});
						}

						$this.viewData.push(data);
						
						// 处理默认值
						// 优先使用 this.selectIndex ；没有选中值，再用默认值value
						/**
						 * 2024-03-04 
						 * 修复：查找懒加载数据中是否存在之前选中的值，没有则默认选中 第一条数据 0 ；
						 * 
						 */
						
						let selectIndex = -1;
						let isInitSelect = false;
						if($this.selectIndex[column+1]!=undefined){
							// 数据中是否存在之前选中数据
							selectIndex = data.findIndex(item=>item[value] == $this.selectValue[column+1][value])
							// selectIndex = $this.selectIndex[column+1];
						}else if($this.value[column+1]!=undefined){
							// 处理默认选中
							selectIndex = data.findIndex(item=>item[value] == $this.value[column+1][value]);
							isInitSelect = true;
						}
						if(selectIndex<0){
							selectIndex = 0;
						}
						
						// 等待列数据渲染完毕
						$this.$nextTick(()=>{
							$this.handleChange({detail:{column:column+1,value:selectIndex}})
							if(isInitSelect){
								// 有默认值，懒加载，处理选中的数据
								$this.selectValue.push(data[selectIndex])
								
							}
						})
					}

				});
			},
			handleChange({
				detail
			}) {

				let {
					column,
					value
				} = detail
				const {
					children
				} = this.options
				
				let info = this.viewData[column][value]
				// 修复nvue问题
				// this.selectIndex[column] = value;
				this.selectIndex.splice(column, 1, value);
				
				// 懒加载，外部加载更新下一层级数据
				if (this.lazy && (!info || !info[children]||info[children].length<1)) {
					this.handleLazyLoad(detail)
					return
				}
				
				// 下一层级
				let nextColumn = column + 1;
				if (!info || !info[children] || info[children].length < 1) {
					// 没有下一层级，则移除viewData 已有的数据；
					this.viewData.length = nextColumn;
					return
				}

				while (info[children] && info[children].length > 0) {
					
					let prevColumnData = this.viewData[nextColumn]||[];
					// 默认第一条数据
					if (this.viewData[nextColumn]) {
						// 修复nvue问题
						// this.viewData[nextColumn] = info[children]
						this.viewData.splice(nextColumn, 1, info[children])
					} else {
						this.viewData.push(info[children]);
					}
					// 重置其他column选择值位0
					// 不重置，相同子级同样选中
					let isSame = this.comparePrevColumnData(prevColumnData,this.viewData[nextColumn],nextColumn);
					if (!isSame) {
						this.selectIndex.splice(nextColumn, 1, 0)
					}
					nextColumn += 1;
					info = info[children][0]
				}
				
				this.viewData.length = nextColumn;
				
				// 调用一次默认选中，触发懒加载判断
				this.handleChange({detail:{column:nextColumn-1,value:this.selectIndex[nextColumn-1]}});
				
			},
			handleConfirm({
				detail
			}) {
				let valueArr = detail.value
				// 已选择
				valueArr.length = this.viewData.length;
				this.selectValue = valueArr.map((val, index) => this.viewData[index][val])

				// 选中值
				// 最后一个选中对象
				let suffix = this.selectValue[this.selectValue.length - 1]
				if (this.checkStrictly && suffix.value === '') {
					this.selectValue.pop()
				}

				this.$emit('ok', this.selectValue[this.selectValue.length - 1], this.selectValue);
			},
			comparePrevColumnData(pre,cur,index){
				const {
					value
				} = this.options
				
				if(!pre[index] || !cur[index]){
					return false;
				}
				return pre[index][value] == cur[index][value]
			}
		}
	};
</script>

<style>

</style>